package org.farng.mp3.object;

import java.util.Arrays;


/**
 * DOCUMENT ME!
 *
 * @author Eric Farng
 * @version $Revision: 1.6 $
 */
public abstract class AbstractMP3Object extends java.lang.Object {
    /** DOCUMENT ME! */
    protected Object value = null;

    /** DOCUMENT ME! */
    protected String identifier = "";

    public AbstractMP3Object() {
        this.value      = null;
        this.identifier = "";
    }

    public AbstractMP3Object(AbstractMP3Object copyObject) {
        // no copy constructor in super class
        this.identifier = new String(copyObject.identifier);

        if (copyObject.value == null) {
            this.value = null;
        } else if (copyObject.value instanceof String) {
            this.value = new String((String) copyObject.value);
        } else if (copyObject.value instanceof Boolean) {
            this.value = new Boolean(((Boolean) copyObject.value).booleanValue());
        } else if (copyObject.value instanceof Byte) {
            this.value = new Byte(((Byte) copyObject.value).byteValue());
        } else if (copyObject.value instanceof Character) {
            this.value = new Character(((Character) copyObject.value).charValue());
        } else if (copyObject.value instanceof Double) {
            this.value = new Double(((Double) copyObject.value).doubleValue());
        } else if (copyObject.value instanceof Float) {
            this.value = new Float(((Float) copyObject.value).floatValue());
        } else if (copyObject.value instanceof Integer) {
            this.value = new Integer(((Integer) copyObject.value).intValue());
        } else if (copyObject.value instanceof Long) {
            this.value = new Long(((Long) copyObject.value).longValue());
        } else if (copyObject.value instanceof Short) {
            this.value = new Short(((Short) copyObject.value).shortValue());
        } else if (copyObject.value instanceof boolean[]) {
            this.value = ((boolean[]) copyObject.value).clone();
        } else if (copyObject.value instanceof byte[]) {
            this.value = ((byte[]) copyObject.value).clone();
        } else if (copyObject.value instanceof char[]) {
            this.value = ((char[]) copyObject.value).clone();
        } else if (copyObject.value instanceof double[]) {
            this.value = ((double[]) copyObject.value).clone();
        } else if (copyObject.value instanceof float[]) {
            this.value = ((float[]) copyObject.value).clone();
        } else if (copyObject.value instanceof int[]) {
            this.value = ((int[]) copyObject.value).clone();
        } else if (copyObject.value instanceof long[]) {
            this.value = ((long[]) copyObject.value).clone();
        } else if (copyObject.value instanceof short[]) {
            this.value = ((short[]) copyObject.value).clone();
        } else if (copyObject.value instanceof Object[]) {
            this.value = ((Object[]) copyObject.value).clone();
        } else {
            throw new UnsupportedOperationException("Unable to create copy of class " + copyObject.getClass());
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getIdentifier() {
        return identifier;
    }

    /**
     * DOCUMENT ME!
     *
     * @param value DOCUMENT ME!
     */
    public void setValue(Object value) {
        this.value = value;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public Object getValue() {
        return value;
    }

    /**
     * DOCUMENT ME!
     *
     * @param arr DOCUMENT ME!
     */
    final public void readByteArray(byte[] arr) {
        readByteArray(arr, 0);
    }

    /**
     * DOCUMENT ME!
     *
     * @param str DOCUMENT ME!
     */
    final public void readString(String str) {
        readString(str, 0);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    abstract public int getSize();

    /**
     * DOCUMENT ME!
     *
     * @param arr DOCUMENT ME!
     * @param offset DOCUMENT ME!
     */
    public void readByteArray(byte[] arr, int offset) {
        readString(new String(arr), offset);
    }

    /**
     * DOCUMENT ME!
     *
     * @param str DOCUMENT ME!
     * @param offset DOCUMENT ME!
     */
    public void readString(String str, int offset) {
        readByteArray(str.substring(offset).getBytes(), 0);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    abstract public String toString();

    /**
     * DOCUMENT ME!
     *
     * @param obj DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public boolean equals(Object obj) {
        if ((obj instanceof AbstractMP3Object) == false) {
            return false;
        }

        AbstractMP3Object object = (AbstractMP3Object) obj;

        if (this.identifier.equals(object.identifier) == false) {
            return false;
        }

        if ((this.value == null) && (object.value == null)) {
            return true;
        } else if ((this.value == null) || (object.value == null)) {
            return false;
        }

        // boolean[]
        if (this.value instanceof boolean[] && object.value instanceof boolean[]) {
            if (Arrays.equals((boolean[]) this.value, (boolean[]) object.value) == false) {
                return false;
            }

            // byte[]
        } else if (this.value instanceof byte[] && object.value instanceof byte[]) {
            if (Arrays.equals((byte[]) this.value, (byte[]) object.value) == false) {
                return false;
            }

            // char[]
        } else if (this.value instanceof char[] && object.value instanceof char[]) {
            if (Arrays.equals((char[]) this.value, (char[]) object.value) == false) {
                return false;
            }

            // double[]
        } else if (this.value instanceof double[] && object.value instanceof double[]) {
            if (Arrays.equals((double[]) this.value, (double[]) object.value) == false) {
                return false;
            }

            // float[]
        } else if (this.value instanceof float[] && object.value instanceof float[]) {
            if (Arrays.equals((float[]) this.value, (float[]) object.value) == false) {
                return false;
            }

            // int[]
        } else if (this.value instanceof int[] && object.value instanceof int[]) {
            if (Arrays.equals((int[]) this.value, (int[]) object.value) == false) {
                return false;
            }

            // long[]
        } else if (this.value instanceof long[] && object.value instanceof long[]) {
            if (Arrays.equals((long[]) this.value, (long[]) object.value) == false) {
                return false;
            }

            // Object[]
        } else if (this.value instanceof Object[] && object.value instanceof Object[]) {
            if (Arrays.equals((Object[]) this.value, (Object[]) object.value) == false) {
                return false;
            }

            // short[]
        } else if (this.value instanceof short[] && object.value instanceof short[]) {
            if (Arrays.equals((short[]) this.value, (short[]) object.value) == false) {
                return false;
            }
        } else if (this.value.equals(object.value) == false) {
            return false;
        }

        return true;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public byte[] writeByteArray() {
        return writeString().getBytes();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String writeString() {
        return new String(writeByteArray());
    }
}